import time

from flask import request, session
from redisconn import redisClient
from flask_restplus import Resource
from rel import rel_api
import hashlib
from app.common import SysResult
from mongoconn import mongoClient
from common import strQ2B

from Rel2021 import Data_Generate
from io import BytesIO
from openpyxl import load_workbook
from openpyxl.writer.excel import save_virtual_workbook
import datetime


def allowed_file(filename):
    '''
    检查函数扩展名是否合法，上传文件，把用户重定向到已经上传文件的url
    :param filename: 文件名
    :return: True or False
    '''
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ('xlsx', 'xls', 'csv')


@rel_api.route('/uploadfile', methods=["POST", "DELETE"])
class Upload(Resource):
    def post(self):
        """
        上传文件
        :return:
        """
        file = request.files['file']
        # 获取文件字节流
        content = file.read()
        # 根据文件内容生成唯一对应的md5
        md5 = hashlib.md5(content).hexdigest()

        # 判断文件类型
        # if "daily report" in file.filename and file.content_type == 'application/octet-stream':
        if "daily report" in file.filename:
            session['daily'] = md5

        # elif file.content_type == 'application/octet-stream':
        else:
            f_num = session.get('f_num', 0)
            f_num += 1
            session['f_num'] = f_num

            f_list = 'f_list_' + str(f_num)
            session[f_list] = (file.filename, md5)

        # 检测到新上传文件后将进度清零
        redisClient.conn.set(session.sid + 'percentage', 0)

        # 建立一个MongoDB client
        mycollection = mongoClient.rel
        is_file_exist = mycollection.find({'_id': md5}).limit(1).count()

        # 如果文件不存在则插入数据
        if not is_file_exist:
            mycollection.insert({
                '_id': md5,
                'content': content,
                'filename': file.filename,
                'mimetype': file.mimetype
            })
        # else:
        #     mycollection.update({'_id':md5}, {'$set': {'filename':file.filename}})

        return SysResult.ok(msg='上传文件成功！')

    def delete(self):
        """
        从session中删除对应的key
        :return:
        """
        file_name = request.json.get('filename', None)

        if "daily report" in file_name:
            session.pop('daily', None)
        else:
            f_num = session['f_num']
            f_list = 'f_list_' + str(f_num)
            for i in range(f_num):
                f_now = 'f_list_' + str(i+1)
                if session[f_now][0] == file_name:
                    session[f_now] = session[f_list]
                    session.pop(f_list)
                    session['f_num'] = f_num - 1
                    break

        return SysResult.ok(msg='文件删除成功')


@rel_api.route('/progress', methods=['GET'])
class Progress(Resource):
    def get(self):
        """
        反馈当前处理的进度
        :return:
        """
        percentage = 0
        try:
            percentage = redisClient.conn.get(session.sid + 'percentage')
        except Exception as e:
            print(e)
        finally:
            redisClient.conn.close()

        if percentage is None:
            percentage = 0
        else:
            percentage = round(float(percentage), 2)
        return SysResult.ok(msg="程序正在运行", data={'percentage': percentage})


@rel_api.route('/session', methods=['DELETE'])
class DeleteSession(Resource):
    def delete(self):
        '''
        刷新页面，清除session缓存
        :return:
        '''
        if 'daily' in session:
            session.pop('daily')
        if 'f_num' in session:
            f_num = session['f_num']
            for i in range(f_num):
                f_list = 'f_list_' + str(i + 1)
                session.pop(f_list)
            session.pop('f_num')

        redisClient.conn.delete(session.sid + 'percentage')
        return SysResult.ok(msg='缓存清除成功')


@rel_api.route('/analysis', methods=['POST'])
class Analysis(Resource):
    def post(self):
        """
        执行数据分析
        :return:
        """
        if session.get('daily') is not None and session.get('f_list_1') is not None:

            redisconn = redisClient.conn
            session['percentage'] = 0
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            mycollection = mongoClient.rel

            file_id_daily = session.get('daily')
            file_num = session.get('f_num')

            session['percentage'] = 12
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            Raw_list = []  # 以workbook类型组成的列表
            for i in range(file_num):
                file_str = 'f_list_' + str(i + 1)
                file_id_list = session.get(file_str)[1]
                file_list = mycollection.find_one({'_id': file_id_list})
                file_content_list = file_list.get('content')
                Raw_list.append(load_workbook(filename=BytesIO(file_content_list)))

            file_daily = mycollection.find_one({'_id': file_id_daily})

            file_content_daily = file_daily.get('content')

            session['percentage'] = 58
            # 将进度保存到redis数据库供前端获取分析进度
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            Raw_daily = load_workbook(filename=BytesIO(file_content_daily))

            session['percentage'] = 84
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            # 生成原始文件
            daily_report = Data_Generate(Raw_daily, Raw_list)

            session['percentage'] = 92
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            # 将数据写入Excel文件
            excel_data = save_virtual_workbook(daily_report)

            session['percentage'] = 98
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            # 获取文件的md5值
            csv_md5 = session.get('daily')

            session['percentage'] = 100
            redisconn.set(session.sid + 'percentage', session.get('percentage'))

            # 切换到relFileToDownload
            mycollection = mongoClient.relFileToDownload

            # 如果该表被处理过，则执行数据更新
            if mycollection.find({'_id': csv_md5}).limit(1).count():
                mycollection.update({'_id': csv_md5}, {'$set': {'data': excel_data}})
            else:
                mycollection.insert({'_id': csv_md5, 'data': excel_data})

            return SysResult.ok(msg='分析完毕！')

        elif session.get('daily') is None:
            return SysResult.error(msg='没有上传DailyReport文件')

        elif session.get('f_list_1') is None:
            return SysResult.error(msg='没有上传细项文件')


@rel_api.route('/download', methods=['GET'])
class Download(Resource):
    def get(self):
        '''
        :return:下载处理完后的文件
        '''
        csv_md5 = session.get('daily')

        mycollection = mongoClient.relFileToDownload
        data = mycollection.find_one({'_id': csv_md5}).get('data')
        project_name = 'Daily_Report_' + datetime.datetime.now().strftime('%Y%m%d')

        from urllib.parse import quote
        from flask import send_file

        # 导出字节流的方式
        filename = quote((strQ2B(project_name) + ".xlsx").encode('utf-8'))
        response = send_file(BytesIO(data),
                             as_attachment=True,
                             attachment_filename=filename,
                             mimetype='application/vnd.ms-excel')
        response.headers["Content-Disposition"] = "attachment; filename=" + filename
        response.headers['Content-Type'] = 'application/x-xlsx'
        return response
